package com.example.gatewayservice.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.List;

@Order(1)
@Component
public class CampusNetworkFilter implements GlobalFilter, Ordered {

    private static final List<String> CAMPUS_IP_RANGES = List.of(
            "10.20.0.0/16"
    );

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();

        // 检查是否为/admin路径
        if (path.startsWith("/admin")|| path.equals("/HomeAdmin")) {
            String clientIp = getClientIp(exchange);

            // 调试信息（生产环境可移除）
            System.out.println("访问/admin路径的客户端IP: " + clientIp);
            System.out.println("允许的IP段: " + CAMPUS_IP_RANGES);

            if (!isIpInCampusRanges(clientIp)) {
                System.out.println("IP " + clientIp + " 不在校园网范围内，拒绝访问");
                exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                return exchange.getResponse().setComplete();
            }

            System.out.println("IP " + clientIp + " 在校园网范围内，允许访问");
        }

        return chain.filter(exchange);
    }

    /**
     * 获取客户端真实IP地址
     */
    private String getClientIp(ServerWebExchange exchange) {
        // 1. 先检查X-Forwarded-For头（如果网关前面有代理）
        String xForwardedFor = exchange.getRequest().getHeaders().getFirst("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            // 取第一个IP（原始客户端IP）
            String clientIp = xForwardedFor.split(",")[0].trim();
            if (!clientIp.isEmpty() && !"unknown".equalsIgnoreCase(clientIp)) {
                return clientIp;
            }
        }

        // 2. 检查其他常见代理头
        String realIp = exchange.getRequest().getHeaders().getFirst("X-Real-IP");
        if (realIp != null && !realIp.isEmpty() && !"unknown".equalsIgnoreCase(realIp)) {
            return realIp;
        }

        // 3. 没有代理头，直接获取远程地址
        InetSocketAddress remoteAddress = exchange.getRequest().getRemoteAddress();
        if (remoteAddress != null) {
            return remoteAddress.getAddress().getHostAddress();
        }
        return "";
    }

    /**
     * 检查IP是否在校园网范围内
     */
    private boolean isIpInCampusRanges(String ip) {
        for (String cidr : CAMPUS_IP_RANGES) {
            if (isIpInCidr(ip, cidr)) {
                return true;
            }
        }
        return false;
    }

    /**
     * CIDR匹配算法实现
     */
    private boolean isIpInCidr(String ip, String cidr) {
        try {
            String[] parts = cidr.split("/");
            String network = parts[0];
            int prefix;

            if (parts.length < 2) {
                prefix = 32; // 如果没有前缀，认为是单个IP
            } else {
                prefix = Integer.parseInt(parts[1]);
            }

            // 将IP地址转换为整数
            long ipLong = ipToLong(ip);
            long networkLong = ipToLong(network);

            // 计算子网掩码
            long mask = (0xFFFFFFFFL) << (32 - prefix);

            // 比较网络地址
            return (ipLong & mask) == (networkLong & mask);

        } catch (Exception e) {
            System.err.println("CIDR匹配错误: " + e.getMessage());
            return false;
        }
    }

    /**
     * 将IP地址转换为long值
     */
    private long ipToLong(String ipAddress) {
        String[] ipAddressInArray = ipAddress.split("\\.");
        long result = 0;
        for (int i = 0; i < ipAddressInArray.length; i++) {
            int power = 3 - i;
            int ip = Integer.parseInt(ipAddressInArray[i]);
            result += ip * Math.pow(256, power);
        }
        return result;
    }

    @Override
    public int getOrder() {
        // 设置为高优先级，确保在其他过滤器之前执行
        return Ordered.HIGHEST_PRECEDENCE;
    }
}